#ifndef HAND_SHAKE_PROTOCOL_HPP
#define HAND_SHAKE_PROTOCOL_HPP

#include <string>
#include <vector>

#ifndef U8Vec
#define U8Vec std::vector<uint8_t>
#endif

struct HandShakeProtocol {

	HandShakeProtocol() {};
	HandShakeProtocol(int shakeNum) { handshakes.resize(shakeNum); };

	std::string getReplies();
	std::string getReply(std::string hint);
	std::string toStr(int indent);
	int restart();

	struct OneShake {
		OneShake() {};
		OneShake(std::string newHint) { hint = newHint; };
		void set(U8Vec& command, std::string& reply, int timeout);
		std::string hint;
		std::string toStr(int indent);
		void restart();
		std::string getReplyStr();

		struct SendContent {
			U8Vec dataToSend;
			int retryNum = 1;
		} toSend;

		struct ReplyExp {
			ReplyExp() {};
			ReplyExp(std::vector<uint8_t> reply, int timeoutIn);
			void resize(int size);
			void set(std::vector<uint8_t> reply, int isTemplate, int parseNum, int timeoutIn);
			void set(std::string reply, int isTemplate, int parseNum, int timeoutIn);
			void add(std::vector<uint8_t> reply, int isTemplate, int parseNum);

			int timeout = -1;
			std::vector<int> isReplyTemplate;
			std::vector<U8Vec> possibleReplies;
			std::vector<int> flagParseNumberInReply;
			U8Vec replyEnd;
		} exp;

		struct ReplyResult {
			void reset();
			// stop hints removed
			// not implemented
			U8Vec reply;
			// among possibilities, not implemented
			int replyTypeIdxOut = -1;
			// even it is float, we copy the binary data here
			std::vector<int> parsedNumberOut;
		} result;
	};
	std::vector<OneShake> handshakes;
	OneShake* getShakeRef(std::string hint);
};

#endif